import { AxiosRequestConfig, AxiosPromise, AxiosResponse } from '../types'
import xhr from '../core/xhr'
import { buildURL } from '../helpers/url'
import { flattenHeaders } from '../helpers/headers'
import transform from '../helpers/transform'
import { isAbsoluteURL, combineURL } from '../helpers/util'

/**
 * 描述 主程序调用入口
 * @param {AxiosRequestConfig} config
 * @returns {AxiosPromise}
 */
function dispatchRequest(config: AxiosRequestConfig): AxiosPromise {
  throwIfCancellationRequested(config)
  processConfig(config)
  return xhr(config).then((res) => {
    return transformResponseData(res)
  })
}

/**
 * 描述 统一对配置进行格式化
 * @param {AxiosRequestConfig} config
 * @returns {void}
 */
function processConfig(config: AxiosRequestConfig): void {
  config.url = tranformURL(config)
  config.data = transform(config.data, config.headers, config.transformRequest!)
  config.headers = flattenHeaders(config.headers, config.method!)
}

/**
 * 描述 针对类 get|GET 请求，对URL做处理
 * @param {AxiosRequestConfig} config
 * @returns {string}
 */
export function tranformURL(config: AxiosRequestConfig): string {
  let { url, params, paramSerializer, baseURL } = config
  if (baseURL && !isAbsoluteURL(url!)) {
    url = combineURL(baseURL, url)
  }
  return buildURL(url!, params, paramSerializer)
}

/**
 * 描述 对响应数据做JSON.parse处理
 * @param {AxiosResponse} config
 * @returns {AxiosPromise}
 */
function transformResponseData(res: AxiosResponse): AxiosResponse {
  res.data = transform(res.data, res.headers, res.config.transformResponse!)
  return res
}

function throwIfCancellationRequested(config: AxiosRequestConfig): void {
  if (config.cancelToken) {
    config.cancelToken.throwIfRequested()
  }
}

export default dispatchRequest
